import sys
import cv2
import numpy as np
from PySide6.QtWidgets import (
    QApplication, QMainWindow, QWidget, QPushButton,
    QVBoxLayout, QHBoxLayout, QFileDialog, QTextEdit, QMessageBox
)
from PySide6.QtCore import QTimer, Qt
from PySide6.QtGui import QImage, QPixmap
from ultralytics import YOLO
from playsound import playsound
from video_widget import VideoWidget
from datetime import datetime

class FireIntrusionApp(QMainWindow):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("火灾检测与区域入侵监测系统")
        self.setGeometry(100, 100, 1200, 800)
        self.setStyleSheet("background-color: #0f172a; color: white;")

        self.video_widget = VideoWidget()
        self.video_widget.setFixedSize(800, 600)

        self.start_btn = QPushButton("开始检测")
        self.stop_btn = QPushButton("停止检测")
        self.open_btn = QPushButton("打开视频文件")
        self.clear_btn = QPushButton("清除检测框")
        self.log_output = QTextEdit()
        self.log_output.setReadOnly(True)

        for btn in [self.start_btn, self.stop_btn, self.open_btn, self.clear_btn]:
            btn.setStyleSheet("background-color: #2563eb;")

        left = QVBoxLayout()
        left.addWidget(self.start_btn)
        left.addWidget(self.stop_btn)
        left.addWidget(self.open_btn)
        left.addWidget(self.clear_btn)
        left.addWidget(self.log_output)
        left.addStretch()
        layout = QHBoxLayout()
        layout.addLayout(left, 2)
        layout.addWidget(self.video_widget, 8)
        container = QWidget()
        container.setLayout(layout)
        self.setCentralWidget(container)

        self.start_btn.clicked.connect(self.start)
        self.stop_btn.clicked.connect(self.stop)
        self.open_btn.clicked.connect(self.open_file)
        self.clear_btn.clicked.connect(self.clear_rect)

        self.cap = None
        self.timer = QTimer()
        self.timer.timeout.connect(self.update_frame)
        self.model = YOLO("yolov8n.pt")
        self.log("✅ 已加载 YOLOv8 模型")
        self.cool = {"fire": False, "intrusion": False}

    def log(self, text):
        self.log_output.append(text)

    def start(self):
        if not self.cap:
            self.cap = cv2.VideoCapture(0)
            self.log("打开摄像头")
        self.timer.start(30)

    def stop(self):
        self.timer.stop()
        if self.cap:
            self.cap.release()
            self.cap = None
            self.log("停止检测")
        self.video_widget.clear_polygon()
        self.cool = {k: False for k in self.cool}

    def open_file(self):
        f, _ = QFileDialog.getOpenFileName(self, "选视频", "", "视频 (*.mp4 *.avi *.mov)")
        if f:
            if self.cap:
                self.cap.release()
            self.cap = cv2.VideoCapture(f)
            self.log(f"打开视频: {f}")
        self.timer.start(30)

    def clear_rect(self):
        self.video_widget.clear_polygon()
        self.log("清除检测框")

    def point_in_rect(self, x, y, rect):
        return rect.contains(x, y)

    def alert(self, kind, msg):
        if kind not in self.cool:
            self.cool[kind] = False

        # 当前已经显示弹窗了 → 覆盖内容
        if hasattr(self, 'alert_box') and self.alert_box.isVisible():
            self.alert_box.setText(msg)
            return

        # 记录冷却状态，避免重复弹窗
        if self.cool[kind]:
            return

        self.cool[kind] = True
        self.log(msg)

        self.alert_box = QMessageBox(self)
        self.alert_box.setWindowTitle("⚠️ 报警")
        self.alert_box.setText(msg)
        self.alert_box.setIcon(QMessageBox.Warning)
        self.alert_box.setStandardButtons(QMessageBox.Ok)
        self.alert_box.show()

        try:
            playsound("alert.wav", block=False)
        except:
            pass

        # 重置冷却时间
        QTimer.singleShot(3000, lambda: self.reset_cool(kind))

    def reset_cool(self, kind):
        self.cool[kind] = False

    def update_frame(self):
        if not (self.cap and self.cap.isOpened()):
            return
        ret, frame = self.cap.read()
        if not ret:
            self.stop()
            return

        res = self.model(frame)[0]
        for b in res.boxes:
            cls_id = int(b.cls[0])
            label = self.model.names[cls_id].lower()
            conf = float(b.conf[0])
            if conf < 0.5:continue
            if label not in ["person", "fire", "smoke"]: continue
            x1, y1, x2, y2 = map(int, b.xyxy[0])
            cx, cy = (x1 + x2)//2, (y1 + y2)//2
            now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
            if label in ["fire", "smoke"]:
                self.alert("fire", f"🔥 火灾报警: 置信度 {conf:.2f}\n时间：{now}")
            if label == "person":
                rect = self.video_widget.rect
                if not rect.isEmpty() and self.point_in_rect(cx, cy, rect):
                    self.alert("intrusion", f"🚷 区域入侵报警：置信度 {conf:.2f}\n时间：{now}")

            cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2)
            cv2.putText(frame, f"{label} {conf:.2f}", (x1, y1-10),
                        cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)

        # 绘制检测框样式
        # rect = self.video_widget.rect
        # if not rect.isEmpty():
        #     x, y, w, h = rect.x(), rect.y(), rect.width(), rect.height()
        #     cv2.rectangle(frame, (x, y), (x+w, y+h), (255, 0, 0), 2)

        img = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        h, w, c = img.shape
        qt = QImage(img.data, w, h, w*c, QImage.Format_RGB888)
        self.video_widget.setPixmap(QPixmap.fromImage(qt).scaled(
            self.video_widget.size(), Qt.KeepAspectRatio, Qt.SmoothTransformation))

if __name__ == "__main__":
    app = QApplication(sys.argv)
    win = FireIntrusionApp()
    win.show()
    sys.exit(app.exec())
